package com.hx.rpc;

import com.hx.entity.RpcRequest;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;

/**
 * @author Huathy
 * @date 2021-10-17 22:34
 * @description
 */
public class ProcessorHandler implements Runnable {

    private Socket socket;
    private Object targetService;

    public ProcessorHandler(Socket socket) {
        this.socket = socket;
    }

    public ProcessorHandler(Socket socket, Object targetService) {
        this.socket = socket;
        this.targetService = targetService;
    }

    @Override
    public void run() {
        ObjectInputStream objectInputStream = null;
        ObjectOutputStream objectOutputStream = null;

        try {
            objectInputStream = new ObjectInputStream(socket.getInputStream());
            objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            //请求输入流中需要那些信息？请求的类、方法名称、参数。
            RpcRequest rpcRequest = (RpcRequest) objectInputStream.readObject();
            //写出
            Object result = this.invoke(rpcRequest);
            objectOutputStream.writeObject(result);
            objectOutputStream.flush();
        } catch (IOException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        } finally {
            try {
                if (objectInputStream != null) {
                    objectInputStream.close();
                }
                if (objectOutputStream != null) {
                    objectOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 反射调用方法
     *
     * @param request
     * @return
     */
    private Object invoke(RpcRequest request) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        Object[] args = request.getParams();
        Class<?>[] types = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
            types[i] = args[i].getClass();
        }
        Class<?> clazz = Class.forName(request.getClassName());
//        Object targetService = clazz.newInstance();
        Method method = clazz.getMethod(request.getMethodName(), types);
        Object result = method.invoke(targetService, args);
        return result;
    }
}
